/**
 * @file otsu.cpp
 * @brief 大津法阈值计算模块实现
 * 
 * 自实现 Otsu's method（最大类间方差法）。
 * 基于灰度直方图统计计算最优阈值。
 */
#include "otsu.h"

unsigned char computeOtsuThreshold(const unsigned char image[][SCALED_WIDTH], int height, int width) 
{
    // TODO: 实现 Otsu 算法
    // 1. 计算灰度直方图
    // 2. 计算总均值
    // 3. 遍历所有阈值计算类间方差
    // 4. 返回最大方差对应的阈值
    
    // 灰度直方图
    int hist[256] = {0};
    int totalPixels = height * width;

    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {
            hist[image[i][j]]++;
        }
    }
    
    // 计算总均值 - 使用float避免TC264软浮点开销
    float totalMean = 0.0f;
    for (int i = 0; i < 256; i++) {
        totalMean += i * static_cast<float>(hist[i]) / totalPixels;
    }
    
    // 寻找最优阈值 - 全部使用float
    float maxBetweenVariance = 0.0f;
    unsigned char bestThreshold = 0;
    
    float weightBackground = 0.0f;  // 背景类概率
    float meanBackground = 0.0f;    // 背景类均值
    
    // 遍历所有可能的阈值 t（0~254），寻找使类间方差最大的阈值
    for (int t = 0; t < 255; t++) {
        // 累加当前阈值 t 对应的背景类像素占比（概率）
        weightBackground += static_cast<float>(hist[t]) / totalPixels;
    
        // 跳过背景类概率过小或过大的情况，避免数值不稳定
        if (weightBackground < 0.001f || weightBackground > 0.999f) {
            continue;
        }
    
        // 累加背景类的灰度均值（按概率加权）
        meanBackground += t * static_cast<float>(hist[t]) / totalPixels;
    
        // 计算前景类灰度均值（总均值减去背景类均值，再按前景类概率归一化）
        float meanForeground = (totalMean - meanBackground) / (1.0f - weightBackground);
    
        // 计算类间方差：w_b * (1 - w_b) * (μ_b - μ_f)^2
        float varianceDiff = meanBackground - meanForeground;
        float betweenVariance = weightBackground * (1.0f - weightBackground) * varianceDiff * varianceDiff;
    
        // 记录最大类间方差及其对应的阈值
        if (betweenVariance > maxBetweenVariance) {
            maxBetweenVariance = betweenVariance;
            bestThreshold = static_cast<unsigned char>(t);
        }
    }
    
    return bestThreshold;
}